{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 1,
   "id": "82614c00-d187-4c9f-b17b-13a89e520c14",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Requirement already satisfied: download in /home/openmind/.local/lib/python3.10/site-packages (0.3.5)\n",
      "Requirement already satisfied: tqdm in /usr/local/python3.10/lib/python3.10/site-packages (from download) (4.67.1)\n",
      "Requirement already satisfied: six in /usr/local/python3.10/lib/python3.10/site-packages (from download) (1.17.0)\n",
      "Requirement already satisfied: requests in /usr/local/python3.10/lib/python3.10/site-packages (from download) (2.32.2)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/python3.10/lib/python3.10/site-packages (from requests->download) (3.4.1)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/python3.10/lib/python3.10/site-packages (from requests->download) (3.10)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/python3.10/lib/python3.10/site-packages (from requests->download) (2.3.0)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/python3.10/lib/python3.10/site-packages (from requests->download) (2025.1.31)\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n",
      "Defaulting to user installation because normal site-packages is not writeable\n",
      "Requirement already satisfied: matplotlib in /home/openmind/.local/lib/python3.10/site-packages (3.10.7)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in /home/openmind/.local/lib/python3.10/site-packages (from matplotlib) (1.3.2)\n",
      "Requirement already satisfied: cycler>=0.10 in /home/openmind/.local/lib/python3.10/site-packages (from matplotlib) (0.12.1)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /home/openmind/.local/lib/python3.10/site-packages (from matplotlib) (4.60.1)\n",
      "Requirement already satisfied: kiwisolver>=1.3.1 in /home/openmind/.local/lib/python3.10/site-packages (from matplotlib) (1.4.9)\n",
      "Requirement already satisfied: numpy>=1.23 in /usr/local/python3.10/lib/python3.10/site-packages (from matplotlib) (1.24.0)\n",
      "Requirement already satisfied: packaging>=20.0 in /usr/local/python3.10/lib/python3.10/site-packages (from matplotlib) (24.2)\n",
      "Requirement already satisfied: pillow>=8 in /usr/local/python3.10/lib/python3.10/site-packages (from matplotlib) (11.1.0)\n",
      "Requirement already satisfied: pyparsing>=3 in /home/openmind/.local/lib/python3.10/site-packages (from matplotlib) (3.2.5)\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /usr/local/python3.10/lib/python3.10/site-packages (from matplotlib) (2.9.0.post0)\n",
      "Requirement already satisfied: six>=1.5 in /usr/local/python3.10/lib/python3.10/site-packages (from python-dateutil>=2.7->matplotlib) (1.17.0)\n",
      "\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m A new release of pip is available: \u001b[0m\u001b[31;49m25.0.1\u001b[0m\u001b[39;49m -> \u001b[0m\u001b[32;49m25.2\u001b[0m\n",
      "\u001b[1m[\u001b[0m\u001b[34;49mnotice\u001b[0m\u001b[1;39;49m]\u001b[0m\u001b[39;49m To update, run: \u001b[0m\u001b[32;49mpip install --upgrade pip\u001b[0m\n"
     ]
    }
   ],
   "source": [
    "!pip install download\n",
    "!pip install matplotlib"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1f9b81fb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz (162.2 MB)\n",
      "\n",
      "file_sizes: 100%|████████████████████████████| 170M/170M [00:04<00:00, 39.6MB/s]\n",
      "Extracting tar.gz file...\n",
      "Successfully downloaded / unzipped to ./datasets-cifar10-bin\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "'./datasets-cifar10-bin'"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "from download import download\n",
    "\n",
    "url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/datasets/cifar-10-binary.tar.gz\"\n",
    "\n",
    "download(url, \"./datasets-cifar10-bin\", kind=\"tar.gz\", replace=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "df7fb621",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/python3.10/lib/python3.10/site-packages/numpy/core/getlimits.py:518: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.\n",
      "  setattr(self, word, getattr(machar, word).flat[0])\n",
      "/usr/local/python3.10/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float64'> type is zero.\n",
      "  return self._float_to_str(self.smallest_subnormal)\n",
      "/usr/local/python3.10/lib/python3.10/site-packages/numpy/core/getlimits.py:518: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.\n",
      "  setattr(self, word, getattr(machar, word).flat[0])\n",
      "/usr/local/python3.10/lib/python3.10/site-packages/numpy/core/getlimits.py:89: UserWarning: The value of the smallest subnormal for <class 'numpy.float32'> type is zero.\n",
      "  return self._float_to_str(self.smallest_subnormal)\n"
     ]
    }
   ],
   "source": [
    "import mindspore as ms\n",
    "import mindspore.dataset as ds\n",
    "import mindspore.dataset.vision as vision\n",
    "import mindspore.dataset.transforms as transforms\n",
    "from mindspore import dtype as mstype\n",
    "\n",
    "data_dir = \"./datasets-cifar10-bin/cifar-10-batches-bin\"  # 数据集根目录\n",
    "batch_size = 256  # 批量大小\n",
    "image_size = 32  # 训练图像空间大小\n",
    "workers = 4  # 并行线程个数\n",
    "num_classes = 10  # 分类数量\n",
    "\n",
    "\n",
    "def create_dataset_cifar10(dataset_dir, usage, resize, batch_size, workers):\n",
    "\n",
    "    data_set = ds.Cifar10Dataset(dataset_dir=dataset_dir,\n",
    "                                 usage=usage,\n",
    "                                 num_parallel_workers=workers,\n",
    "                                 shuffle=True)\n",
    "\n",
    "    trans = []\n",
    "    if usage == \"train\":\n",
    "        trans += [\n",
    "            vision.RandomCrop((32, 32), (4, 4, 4, 4)),\n",
    "            vision.RandomHorizontalFlip(prob=0.5)\n",
    "        ]\n",
    "\n",
    "    trans += [\n",
    "        vision.Resize(resize),\n",
    "        vision.Rescale(1.0 / 255.0, 0.0),\n",
    "        vision.Normalize([0.4914, 0.4822, 0.4465], [0.2023, 0.1994, 0.2010]),\n",
    "        vision.HWC2CHW()\n",
    "    ]\n",
    "\n",
    "    target_trans = transforms.TypeCast(mstype.int32)\n",
    "\n",
    "    # 数据映射操作\n",
    "    data_set = data_set.map(operations=trans,\n",
    "                            input_columns='image',\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    data_set = data_set.map(operations=target_trans,\n",
    "                            input_columns='label',\n",
    "                            num_parallel_workers=workers)\n",
    "\n",
    "    # 批量操作\n",
    "    data_set = data_set.batch(batch_size)\n",
    "\n",
    "    return data_set\n",
    "\n",
    "\n",
    "# 获取处理后的训练与测试数据集\n",
    "\n",
    "dataset_train = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                       usage=\"train\",\n",
    "                                       resize=image_size,\n",
    "                                       batch_size=batch_size,\n",
    "                                       workers=workers)\n",
    "step_size_train = dataset_train.get_dataset_size()\n",
    "\n",
    "dataset_val = create_dataset_cifar10(dataset_dir=data_dir,\n",
    "                                     usage=\"test\",\n",
    "                                     resize=image_size,\n",
    "                                     batch_size=batch_size,\n",
    "                                     workers=workers)\n",
    "step_size_val = dataset_val.get_dataset_size()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "c3ffabb3",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Image shape: (256, 3, 32, 32), Label shape: (256,)\n",
      "Labels: [1 8 8 7 6 9]\n"
     ]
    },
    {
     "data": {
      "image/png": "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duzYQeeddx41NzfTQw89dGhMoSMIIbfccktARMFHPvIR1v/e9743aGlpCYIgCNatWxcQUXDNNdewmL/5m78JiCh45JFHDvV1d3cHRBSsWbOGxd52220BEQWDg4OvOZbvf//7geu6weOPP876//3f/z0gouDJJ588rGsE4WPt2rUBEQU/+tGPDvVdddVVAREFn/nMZ1jsz372s4CIgn/4h39g/ZdffnngOE6wffv2IAiC4IUXXgiIKLjxxhtZ3NVXXx0QUXDLLbe8ORcD3rJ89atfDYgo2LVrF+snosB13WDDhg2s/3fzeu3atax/165dAREFd9xxx6G+s88+O6irqwv6+vpYrO/7h/77d+v/4OBgsGnTpqCrqyt4+9vfHoyMjByR6zteCXWa4GMf+xhrn3XWWTQ8PEzj4+N0//33ExHRX//1X7OYm266iYiI7rvvPtY/e/ZsuuCCC1jf73K3//Vf/0W+75tj+NGPfkSLFy+mRYsW0dDQ0KH/nXfeeUREtHbt2sO7OAB+j49//OOsff/995PneXTDDTew/ptuuomCIKAHHniAiIjWrFlDRETXX389i/vUpz71Jo4WhJXVq1fTkiVLDuuzg4OD9Nhjj9FHPvIRmjVrFvs3x3FU/Pr162n16tXU09NDDz/8MDU1NR3Wed8qhHozICfM7ybD6Ogo9fX1keu6NG/ePBbT2dlJjY2N1NfXx/pnz56tjv+nf/qndMYZZ9A111xDHR0d9IEPfIDuuecetjHYtm0bbdiwgdra2tj/FixYQET/vygMgMMlEonQjBkzWF9fXx91dXVRXV0d61+8ePGhf//d/7uuq+a3fC8AOBJY62i17Ny5k4iIli1bVlX8e97zHqqrq6Nf/epXVF9ff9jnfasQas2A53lmf/B7AiprR2mRTCbNvscee4zWrl1L9913H61Zs4Z++MMf0nnnnUcPPvggeZ5Hvu/T8uXL6Wtf+5p53JkzZ1Z1fgBei3g8Tq4b6n0/OE6w1tHXWoMrlcofda73v//9dNddd9Hdd99N11133R91rLcCod4M/CG6u7vJ933atm3bod+WiIj6+/spnU5Xbebiui6df/75dP7559PXvvY1+qd/+ie6+eabae3atfSOd7yD5s6dSy+//DKdf/75VW88APhj6e7upocffpgmJibYtwObN28+9O+/+3/f92nXrl00f/78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",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "\n",
    "data_iter = next(dataset_train.create_dict_iterator())\n",
    "\n",
    "images = data_iter[\"image\"].asnumpy()\n",
    "labels = data_iter[\"label\"].asnumpy()\n",
    "print(f\"Image shape: {images.shape}, Label shape: {labels.shape}\")\n",
    "\n",
    "# 训练数据集中，前六张图片所对应的标签\n",
    "print(f\"Labels: {labels[:6]}\")\n",
    "\n",
    "classes = []\n",
    "\n",
    "with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "    for line in f:\n",
    "        line = line.rstrip()\n",
    "        if line:\n",
    "            classes.append(line)\n",
    "\n",
    "# 训练数据集的前六张图片\n",
    "plt.figure()\n",
    "for i in range(6):\n",
    "    plt.subplot(2, 3, i + 1)\n",
    "    image_trans = np.transpose(images[i], (1, 2, 0))\n",
    "    mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "    std = np.array([0.2023, 0.1994, 0.2010])\n",
    "    image_trans = std * image_trans + mean\n",
    "    image_trans = np.clip(image_trans, 0, 1)\n",
    "    plt.title(f\"{classes[labels[i]]}\")\n",
    "    plt.imshow(image_trans)\n",
    "    plt.axis(\"off\")\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "c7ac0e2d",
   "metadata": {},
   "outputs": [],
   "source": [
    "from typing import Type, Union, List, Optional\n",
    "import mindspore.nn as nn\n",
    "from mindspore.common.initializer import Normal\n",
    "\n",
    "# 初始化卷积层与BatchNorm的参数\n",
    "weight_init = Normal(mean=0, sigma=0.02)\n",
    "gamma_init = Normal(mean=1, sigma=0.02)\n",
    "\n",
    "class ResidualBlockBase(nn.Cell):\n",
    "    expansion: int = 1  # 最后一个卷积核数量与第一个卷积核数量相等\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, norm: Optional[nn.Cell] = None,\n",
    "                 down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlockBase, self).__init__()\n",
    "        if not norm:\n",
    "            self.norm = nn.BatchNorm2d(out_channel)\n",
    "        else:\n",
    "            self.norm = norm\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.conv2 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=3, weight_init=weight_init)\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "        \"\"\"ResidualBlockBase construct.\"\"\"\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "0d46f98e",
   "metadata": {},
   "outputs": [],
   "source": [
    "class ResidualBlock(nn.Cell):\n",
    "    expansion = 4  # 最后一个卷积核的数量是第一个卷积核数量的4倍\n",
    "\n",
    "    def __init__(self, in_channel: int, out_channel: int,\n",
    "                 stride: int = 1, down_sample: Optional[nn.Cell] = None) -> None:\n",
    "        super(ResidualBlock, self).__init__()\n",
    "\n",
    "        self.conv1 = nn.Conv2d(in_channel, out_channel,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm1 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv2 = nn.Conv2d(out_channel, out_channel,\n",
    "                               kernel_size=3, stride=stride,\n",
    "                               weight_init=weight_init)\n",
    "        self.norm2 = nn.BatchNorm2d(out_channel)\n",
    "        self.conv3 = nn.Conv2d(out_channel, out_channel * self.expansion,\n",
    "                               kernel_size=1, weight_init=weight_init)\n",
    "        self.norm3 = nn.BatchNorm2d(out_channel * self.expansion)\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        self.down_sample = down_sample\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        identity = x  # shortcuts分支\n",
    "\n",
    "        out = self.conv1(x)  # 主分支第一层：1*1卷积层\n",
    "        out = self.norm1(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv2(out)  # 主分支第二层：3*3卷积层\n",
    "        out = self.norm2(out)\n",
    "        out = self.relu(out)\n",
    "        out = self.conv3(out)  # 主分支第三层：1*1卷积层\n",
    "        out = self.norm3(out)\n",
    "\n",
    "        if self.down_sample is not None:\n",
    "            identity = self.down_sample(x)\n",
    "\n",
    "        out += identity  # 输出为主分支与shortcuts之和\n",
    "        out = self.relu(out)\n",
    "\n",
    "        return out"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "3dfa40a1",
   "metadata": {},
   "outputs": [],
   "source": [
    "def make_layer(last_out_channel, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "               channel: int, block_nums: int, stride: int = 1):\n",
    "    down_sample = None  # shortcuts分支\n",
    "\n",
    "    if stride != 1 or last_out_channel != channel * block.expansion:\n",
    "\n",
    "        down_sample = nn.SequentialCell([\n",
    "            nn.Conv2d(last_out_channel, channel * block.expansion,\n",
    "                      kernel_size=1, stride=stride, weight_init=weight_init),\n",
    "            nn.BatchNorm2d(channel * block.expansion, gamma_init=gamma_init)\n",
    "        ])\n",
    "\n",
    "    layers = []\n",
    "    layers.append(block(last_out_channel, channel, stride=stride, down_sample=down_sample))\n",
    "\n",
    "    in_channel = channel * block.expansion\n",
    "    # 堆叠残差网络\n",
    "    for _ in range(1, block_nums):\n",
    "\n",
    "        layers.append(block(in_channel, channel))\n",
    "\n",
    "    return nn.SequentialCell(layers)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "1ebef3d0",
   "metadata": {},
   "outputs": [],
   "source": [
    "from mindspore import load_checkpoint, load_param_into_net\n",
    "\n",
    "\n",
    "class ResNet(nn.Cell):\n",
    "    def __init__(self, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "                 layer_nums: List[int], num_classes: int, input_channel: int) -> None:\n",
    "        super(ResNet, self).__init__()\n",
    "\n",
    "        self.relu = nn.ReLU()\n",
    "        # 第一个卷积层，输入channel为3（彩色图像），输出channel为64\n",
    "        self.conv1 = nn.Conv2d(3, 64, kernel_size=7, stride=2, weight_init=weight_init)\n",
    "        self.norm = nn.BatchNorm2d(64)\n",
    "        # 最大池化层，缩小图片的尺寸\n",
    "        self.max_pool = nn.MaxPool2d(kernel_size=3, stride=2, pad_mode='same')\n",
    "        # 各个残差网络结构块定义\n",
    "        self.layer1 = make_layer(64, block, 64, layer_nums[0])\n",
    "        self.layer2 = make_layer(64 * block.expansion, block, 128, layer_nums[1], stride=2)\n",
    "        self.layer3 = make_layer(128 * block.expansion, block, 256, layer_nums[2], stride=2)\n",
    "        self.layer4 = make_layer(256 * block.expansion, block, 512, layer_nums[3], stride=2)\n",
    "        # 平均池化层\n",
    "        self.avg_pool = nn.AvgPool2d()\n",
    "        # flattern层\n",
    "        self.flatten = nn.Flatten()\n",
    "        # 全连接层\n",
    "        self.fc = nn.Dense(in_channels=input_channel, out_channels=num_classes)\n",
    "\n",
    "    def construct(self, x):\n",
    "\n",
    "        x = self.conv1(x)\n",
    "        x = self.norm(x)\n",
    "        x = self.relu(x)\n",
    "        x = self.max_pool(x)\n",
    "\n",
    "        x = self.layer1(x)\n",
    "        x = self.layer2(x)\n",
    "        x = self.layer3(x)\n",
    "        x = self.layer4(x)\n",
    "\n",
    "        x = self.avg_pool(x)\n",
    "        x = self.flatten(x)\n",
    "        x = self.fc(x)\n",
    "\n",
    "        return x"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "d16e658e",
   "metadata": {},
   "outputs": [],
   "source": [
    "def _resnet(model_url: str, block: Type[Union[ResidualBlockBase, ResidualBlock]],\n",
    "            layers: List[int], num_classes: int, pretrained: bool, pretrained_ckpt: str,\n",
    "            input_channel: int):\n",
    "    model = ResNet(block, layers, num_classes, input_channel)\n",
    "\n",
    "    if pretrained:\n",
    "        # 加载预训练模型\n",
    "        download(url=model_url, path=pretrained_ckpt, replace=True)\n",
    "        param_dict = load_checkpoint(pretrained_ckpt)\n",
    "        load_param_into_net(model, param_dict)\n",
    "\n",
    "    return model\n",
    "\n",
    "\n",
    "def resnet50(num_classes: int = 1000, pretrained: bool = False):\n",
    "    \"\"\"ResNet50模型\"\"\"\n",
    "    resnet50_url = \"https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt\"\n",
    "    resnet50_ckpt = \"./LoadPretrainedModel/resnet50_224_new.ckpt\"\n",
    "    return _resnet(resnet50_url, ResidualBlock, [3, 4, 6, 3], num_classes,\n",
    "                   pretrained, resnet50_ckpt, 2048)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "9cf10c03",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "[WARNING] DEVICE(765,ffff945ce800,python3.10):2025-10-17-06:09:07.938.362 [mindspore/ccsrc/plugin/device/ascend/hal/device/ascend_vmm_adapter.h:149] CheckVmmDriverVersion] Open file /etc/ascend_install.info failed.\n",
      "[WARNING] DEVICE(765,ffff945ce800,python3.10):2025-10-17-06:09:07.938.446 [mindspore/ccsrc/plugin/device/ascend/hal/device/ascend_vmm_adapter.h:177] CheckVmmDriverVersion] Open file /usr/local/Ascend/driver/version.info failed.\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Downloading data from https://mindspore-website.obs.cn-north-4.myhuaweicloud.com/notebook/models/application/resnet50_224_new.ckpt (97.7 MB)\n",
      "\n",
      "file_sizes: 100%|████████████████████████████| 102M/102M [00:03<00:00, 32.9MB/s]\n",
      "Successfully downloaded file to ./LoadPretrainedModel/resnet50_224_new.ckpt\n"
     ]
    }
   ],
   "source": [
    "# 定义ResNet50网络\n",
    "network = resnet50(pretrained=True)\n",
    "\n",
    "# 全连接层输入层的大小\n",
    "in_channel = network.fc.in_channels\n",
    "fc = nn.Dense(in_channels=in_channel, out_channels=10)\n",
    "# 重置全连接层\n",
    "network.fc = fc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "e1c632ff",
   "metadata": {},
   "outputs": [],
   "source": [
    "# 设置学习率\n",
    "num_epochs = 80\n",
    "lr = nn.cosine_decay_lr(min_lr=0.00001, max_lr=0.001, total_step=step_size_train * num_epochs,\n",
    "                        step_per_epoch=step_size_train, decay_epoch=num_epochs)\n",
    "# 定义优化器和损失函数\n",
    "opt = nn.Momentum(params=network.trainable_params(), learning_rate=lr, momentum=0.9)\n",
    "loss_fn = nn.SoftmaxCrossEntropyWithLogits(sparse=True, reduction='mean')\n",
    "\n",
    "\n",
    "def forward_fn(inputs, targets):\n",
    "    logits = network(inputs)\n",
    "    loss = loss_fn(logits, targets)\n",
    "    return loss\n",
    "\n",
    "\n",
    "grad_fn = ms.value_and_grad(forward_fn, None, opt.parameters)\n",
    "\n",
    "\n",
    "def train_step(inputs, targets):\n",
    "    loss, grads = grad_fn(inputs, targets)\n",
    "    opt(grads)\n",
    "    return loss"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "id": "b627e30c",
   "metadata": {},
   "outputs": [],
   "source": [
    "import os\n",
    "\n",
    "# 创建迭代器\n",
    "data_loader_train = dataset_train.create_tuple_iterator(num_epochs=num_epochs)\n",
    "data_loader_val = dataset_val.create_tuple_iterator(num_epochs=num_epochs)\n",
    "\n",
    "# 最佳模型存储路径\n",
    "best_acc = 0\n",
    "best_ckpt_dir = \"./BestCheckpoint\"\n",
    "best_ckpt_path = \"./BestCheckpoint/resnet50-best.ckpt\"\n",
    "\n",
    "if not os.path.exists(best_ckpt_dir):\n",
    "    os.mkdir(best_ckpt_dir)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "id": "8a5170df",
   "metadata": {},
   "outputs": [],
   "source": [
    "import mindspore.ops as ops\n",
    "\n",
    "\n",
    "def train(data_loader, epoch):\n",
    "    \"\"\"模型训练\"\"\"\n",
    "    losses = []\n",
    "    network.set_train(True)\n",
    "\n",
    "    for i, (images, labels) in enumerate(data_loader):\n",
    "        loss = train_step(images, labels)\n",
    "        if i % 100 == 0 or i == step_size_train - 1:\n",
    "            print('Epoch: [%3d/%3d], Steps: [%3d/%3d], Train Loss: [%5.3f]' %\n",
    "                  (epoch + 1, num_epochs, i + 1, step_size_train, loss))\n",
    "        losses.append(loss)\n",
    "\n",
    "    return sum(losses) / len(losses)\n",
    "\n",
    "\n",
    "def evaluate(data_loader):\n",
    "    \"\"\"模型验证\"\"\"\n",
    "    network.set_train(False)\n",
    "\n",
    "    correct_num = 0.0  # 预测正确个数\n",
    "    total_num = 0.0  # 预测总数\n",
    "\n",
    "    for images, labels in data_loader:\n",
    "        logits = network(images)\n",
    "        pred = logits.argmax(axis=1)  # 预测结果\n",
    "        correct = ops.equal(pred, labels).reshape((-1, ))\n",
    "        correct_num += correct.sum().asnumpy()\n",
    "        total_num += correct.shape[0]\n",
    "\n",
    "    acc = correct_num / total_num  # 准确率\n",
    "\n",
    "    return acc"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "562a04ca",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Start Training Loop ...\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe/impl/util/util_conv2d_dynamic.py:130: UserWarning: conv2d fmap ori_range changed from [[32, 2147483647], [2048, 2048], [1, 3], [1, 3]] to [[32, 2147483647], [2048, 2048], [1, 3], (1, 3)].\n",
      "  warnings.warn(to_print)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      ".......Epoch: [  1/ 80], Steps: [  1/196], Train Loss: [2.397]\n",
      ".Epoch: [  1/ 80], Steps: [196/196], Train Loss: [1.033]\n"
     ]
    },
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "/usr/local/Ascend/ascend-toolkit/latest/opp/built-in/op_impl/ai_core/tbe/impl/util/util_conv2d_dynamic.py:130: UserWarning: conv2d fmap ori_range changed from [[16, 31], [2048, 2048], [1, 3], [1, 3]] to [[16, 31], [2048, 2048], [1, 3], (1, 3)].\n",
      "  warnings.warn(to_print)\n"
     ]
    },
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "--------------------------------------------------\n",
      "Epoch: [  1/ 80], Average Train Loss: [1.635], Accuracy: [0.599]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/ 80], Steps: [  1/196], Train Loss: [1.083]\n",
      "Epoch: [  2/ 80], Steps: [101/196], Train Loss: [1.105]\n",
      "Epoch: [  2/ 80], Steps: [196/196], Train Loss: [0.980]\n",
      "--------------------------------------------------\n",
      "Epoch: [  2/ 80], Average Train Loss: [0.993], Accuracy: [0.694]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/ 80], Steps: [  1/196], Train Loss: [0.980]\n",
      "Epoch: [  3/ 80], Steps: [196/196], Train Loss: [0.753]\n",
      "--------------------------------------------------\n",
      "Epoch: [  3/ 80], Average Train Loss: [0.817], Accuracy: [0.734]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/ 80], Steps: [  1/196], Train Loss: [0.743]\n",
      "Epoch: [  4/ 80], Steps: [101/196], Train Loss: [0.677]\n",
      "Epoch: [  4/ 80], Steps: [196/196], Train Loss: [0.799]\n",
      "--------------------------------------------------\n",
      "Epoch: [  4/ 80], Average Train Loss: [0.721], Accuracy: [0.761]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/ 80], Steps: [  1/196], Train Loss: [0.725]\n",
      "Epoch: [  5/ 80], Steps: [101/196], Train Loss: [0.563]\n",
      "Epoch: [  5/ 80], Steps: [196/196], Train Loss: [0.570]\n",
      "--------------------------------------------------\n",
      "Epoch: [  5/ 80], Average Train Loss: [0.647], Accuracy: [0.774]\n",
      "--------------------------------------------------\n",
      "Epoch: [  6/ 80], Steps: [  1/196], Train Loss: [0.666]\n",
      "Epoch: [  6/ 80], Steps: [101/196], Train Loss: [0.506]\n",
      "Epoch: [  6/ 80], Steps: [196/196], Train Loss: [0.676]\n",
      "--------------------------------------------------\n",
      "Epoch: [  6/ 80], Average Train Loss: [0.594], Accuracy: [0.789]\n",
      "--------------------------------------------------\n",
      "Epoch: [  7/ 80], Steps: [  1/196], Train Loss: [0.651]\n",
      "Epoch: [  7/ 80], Steps: [101/196], Train Loss: [0.541]\n",
      "Epoch: [  7/ 80], Steps: [196/196], Train Loss: [0.722]\n",
      "--------------------------------------------------\n",
      "Epoch: [  7/ 80], Average Train Loss: [0.551], Accuracy: [0.798]\n",
      "--------------------------------------------------\n",
      "Epoch: [  8/ 80], Steps: [  1/196], Train Loss: [0.415]\n",
      "Epoch: [  8/ 80], Steps: [101/196], Train Loss: [0.480]\n",
      "Epoch: [  8/ 80], Steps: [196/196], Train Loss: [0.574]\n",
      "--------------------------------------------------\n",
      "Epoch: [  8/ 80], Average Train Loss: [0.510], Accuracy: [0.804]\n",
      "--------------------------------------------------\n",
      "Epoch: [  9/ 80], Steps: [  1/196], Train Loss: [0.474]\n",
      "Epoch: [  9/ 80], Steps: [101/196], Train Loss: [0.362]\n",
      "Epoch: [  9/ 80], Steps: [196/196], Train Loss: [0.600]\n",
      "--------------------------------------------------\n",
      "Epoch: [  9/ 80], Average Train Loss: [0.472], Accuracy: [0.810]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 10/ 80], Steps: [  1/196], Train Loss: [0.386]\n",
      "Epoch: [ 10/ 80], Steps: [101/196], Train Loss: [0.357]\n",
      "Epoch: [ 10/ 80], Steps: [196/196], Train Loss: [0.489]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 10/ 80], Average Train Loss: [0.446], Accuracy: [0.812]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 11/ 80], Steps: [  1/196], Train Loss: [0.488]\n",
      "Epoch: [ 11/ 80], Steps: [101/196], Train Loss: [0.423]\n",
      "Epoch: [ 11/ 80], Steps: [196/196], Train Loss: [0.641]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 11/ 80], Average Train Loss: [0.420], Accuracy: [0.818]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 12/ 80], Steps: [  1/196], Train Loss: [0.345]\n",
      "Epoch: [ 12/ 80], Steps: [101/196], Train Loss: [0.447]\n",
      "Epoch: [ 12/ 80], Steps: [196/196], Train Loss: [0.437]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 12/ 80], Average Train Loss: [0.390], Accuracy: [0.819]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 13/ 80], Steps: [  1/196], Train Loss: [0.322]\n",
      "Epoch: [ 13/ 80], Steps: [101/196], Train Loss: [0.356]\n",
      "Epoch: [ 13/ 80], Steps: [196/196], Train Loss: [0.228]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 13/ 80], Average Train Loss: [0.363], Accuracy: [0.823]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 14/ 80], Steps: [  1/196], Train Loss: [0.293]\n",
      "Epoch: [ 14/ 80], Steps: [101/196], Train Loss: [0.434]\n",
      "Epoch: [ 14/ 80], Steps: [196/196], Train Loss: [0.425]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 14/ 80], Average Train Loss: [0.348], Accuracy: [0.823]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 15/ 80], Steps: [  1/196], Train Loss: [0.327]\n",
      "Epoch: [ 15/ 80], Steps: [101/196], Train Loss: [0.345]\n",
      "Epoch: [ 15/ 80], Steps: [196/196], Train Loss: [0.292]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 15/ 80], Average Train Loss: [0.327], Accuracy: [0.828]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 16/ 80], Steps: [  1/196], Train Loss: [0.293]\n",
      "Epoch: [ 16/ 80], Steps: [101/196], Train Loss: [0.295]\n",
      "Epoch: [ 16/ 80], Steps: [196/196], Train Loss: [0.265]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 16/ 80], Average Train Loss: [0.307], Accuracy: [0.831]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 17/ 80], Steps: [  1/196], Train Loss: [0.324]\n",
      "Epoch: [ 17/ 80], Steps: [101/196], Train Loss: [0.211]\n",
      "Epoch: [ 17/ 80], Steps: [196/196], Train Loss: [0.343]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 17/ 80], Average Train Loss: [0.283], Accuracy: [0.829]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 18/ 80], Steps: [  1/196], Train Loss: [0.255]\n",
      "Epoch: [ 18/ 80], Steps: [101/196], Train Loss: [0.228]\n",
      "Epoch: [ 18/ 80], Steps: [196/196], Train Loss: [0.227]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 18/ 80], Average Train Loss: [0.269], Accuracy: [0.830]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 19/ 80], Steps: [  1/196], Train Loss: [0.220]\n",
      "Epoch: [ 19/ 80], Steps: [101/196], Train Loss: [0.219]\n",
      "Epoch: [ 19/ 80], Steps: [196/196], Train Loss: [0.449]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 19/ 80], Average Train Loss: [0.255], Accuracy: [0.832]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 20/ 80], Steps: [  1/196], Train Loss: [0.190]\n",
      "Epoch: [ 20/ 80], Steps: [101/196], Train Loss: [0.211]\n",
      "Epoch: [ 20/ 80], Steps: [196/196], Train Loss: [0.274]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 20/ 80], Average Train Loss: [0.240], Accuracy: [0.833]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 21/ 80], Steps: [  1/196], Train Loss: [0.281]\n",
      "Epoch: [ 21/ 80], Steps: [101/196], Train Loss: [0.267]\n",
      "Epoch: [ 21/ 80], Steps: [196/196], Train Loss: [0.256]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 21/ 80], Average Train Loss: [0.227], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 22/ 80], Steps: [  1/196], Train Loss: [0.146]\n",
      "Epoch: [ 22/ 80], Steps: [101/196], Train Loss: [0.197]\n",
      "Epoch: [ 22/ 80], Steps: [196/196], Train Loss: [0.277]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 22/ 80], Average Train Loss: [0.212], Accuracy: [0.832]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 23/ 80], Steps: [  1/196], Train Loss: [0.217]\n",
      "Epoch: [ 23/ 80], Steps: [101/196], Train Loss: [0.192]\n",
      "Epoch: [ 23/ 80], Steps: [196/196], Train Loss: [0.245]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 23/ 80], Average Train Loss: [0.191], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 24/ 80], Steps: [  1/196], Train Loss: [0.254]\n",
      "Epoch: [ 24/ 80], Steps: [101/196], Train Loss: [0.214]\n",
      "Epoch: [ 24/ 80], Steps: [196/196], Train Loss: [0.181]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 24/ 80], Average Train Loss: [0.185], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 25/ 80], Steps: [  1/196], Train Loss: [0.150]\n",
      "Epoch: [ 25/ 80], Steps: [101/196], Train Loss: [0.148]\n",
      "Epoch: [ 25/ 80], Steps: [196/196], Train Loss: [0.433]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 25/ 80], Average Train Loss: [0.177], Accuracy: [0.837]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 26/ 80], Steps: [  1/196], Train Loss: [0.168]\n",
      "Epoch: [ 26/ 80], Steps: [101/196], Train Loss: [0.195]\n",
      "Epoch: [ 26/ 80], Steps: [196/196], Train Loss: [0.148]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 26/ 80], Average Train Loss: [0.164], Accuracy: [0.834]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 27/ 80], Steps: [  1/196], Train Loss: [0.166]\n",
      "Epoch: [ 27/ 80], Steps: [101/196], Train Loss: [0.164]\n",
      "Epoch: [ 27/ 80], Steps: [196/196], Train Loss: [0.283]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 27/ 80], Average Train Loss: [0.149], Accuracy: [0.834]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 28/ 80], Steps: [  1/196], Train Loss: [0.181]\n",
      "Epoch: [ 28/ 80], Steps: [101/196], Train Loss: [0.120]\n",
      "Epoch: [ 28/ 80], Steps: [196/196], Train Loss: [0.235]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 28/ 80], Average Train Loss: [0.145], Accuracy: [0.834]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 29/ 80], Steps: [  1/196], Train Loss: [0.089]\n",
      "Epoch: [ 29/ 80], Steps: [101/196], Train Loss: [0.086]\n",
      "Epoch: [ 29/ 80], Steps: [196/196], Train Loss: [0.206]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 29/ 80], Average Train Loss: [0.138], Accuracy: [0.832]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 30/ 80], Steps: [  1/196], Train Loss: [0.190]\n",
      "Epoch: [ 30/ 80], Steps: [101/196], Train Loss: [0.071]\n",
      "Epoch: [ 30/ 80], Steps: [196/196], Train Loss: [0.124]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 30/ 80], Average Train Loss: [0.130], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 31/ 80], Steps: [  1/196], Train Loss: [0.108]\n",
      "Epoch: [ 31/ 80], Steps: [101/196], Train Loss: [0.134]\n",
      "Epoch: [ 31/ 80], Steps: [196/196], Train Loss: [0.242]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 31/ 80], Average Train Loss: [0.123], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 32/ 80], Steps: [  1/196], Train Loss: [0.105]\n",
      "Epoch: [ 32/ 80], Steps: [101/196], Train Loss: [0.130]\n",
      "Epoch: [ 32/ 80], Steps: [196/196], Train Loss: [0.116]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 32/ 80], Average Train Loss: [0.116], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 33/ 80], Steps: [  1/196], Train Loss: [0.138]\n",
      "Epoch: [ 33/ 80], Steps: [101/196], Train Loss: [0.096]\n",
      "Epoch: [ 33/ 80], Steps: [196/196], Train Loss: [0.078]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 33/ 80], Average Train Loss: [0.108], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 34/ 80], Steps: [  1/196], Train Loss: [0.098]\n",
      "Epoch: [ 34/ 80], Steps: [101/196], Train Loss: [0.048]\n",
      "Epoch: [ 34/ 80], Steps: [196/196], Train Loss: [0.108]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 34/ 80], Average Train Loss: [0.101], Accuracy: [0.840]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 35/ 80], Steps: [  1/196], Train Loss: [0.085]\n",
      "Epoch: [ 35/ 80], Steps: [101/196], Train Loss: [0.075]\n",
      "Epoch: [ 35/ 80], Steps: [196/196], Train Loss: [0.172]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 35/ 80], Average Train Loss: [0.099], Accuracy: [0.841]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 36/ 80], Steps: [  1/196], Train Loss: [0.061]\n",
      "Epoch: [ 36/ 80], Steps: [101/196], Train Loss: [0.089]\n",
      "Epoch: [ 36/ 80], Steps: [196/196], Train Loss: [0.193]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 36/ 80], Average Train Loss: [0.093], Accuracy: [0.837]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 37/ 80], Steps: [  1/196], Train Loss: [0.105]\n",
      "Epoch: [ 37/ 80], Steps: [101/196], Train Loss: [0.102]\n",
      "Epoch: [ 37/ 80], Steps: [196/196], Train Loss: [0.203]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 37/ 80], Average Train Loss: [0.089], Accuracy: [0.836]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 38/ 80], Steps: [  1/196], Train Loss: [0.061]\n",
      "Epoch: [ 38/ 80], Steps: [101/196], Train Loss: [0.055]\n",
      "Epoch: [ 38/ 80], Steps: [196/196], Train Loss: [0.102]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 38/ 80], Average Train Loss: [0.083], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 39/ 80], Steps: [  1/196], Train Loss: [0.036]\n",
      "Epoch: [ 39/ 80], Steps: [101/196], Train Loss: [0.084]\n",
      "Epoch: [ 39/ 80], Steps: [196/196], Train Loss: [0.028]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 39/ 80], Average Train Loss: [0.077], Accuracy: [0.836]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 40/ 80], Steps: [  1/196], Train Loss: [0.080]\n",
      "Epoch: [ 40/ 80], Steps: [101/196], Train Loss: [0.105]\n",
      "Epoch: [ 40/ 80], Steps: [196/196], Train Loss: [0.155]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 40/ 80], Average Train Loss: [0.075], Accuracy: [0.836]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 41/ 80], Steps: [  1/196], Train Loss: [0.065]\n",
      "Epoch: [ 41/ 80], Steps: [101/196], Train Loss: [0.089]\n",
      "Epoch: [ 41/ 80], Steps: [196/196], Train Loss: [0.192]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 41/ 80], Average Train Loss: [0.071], Accuracy: [0.835]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 42/ 80], Steps: [  1/196], Train Loss: [0.047]\n",
      "Epoch: [ 42/ 80], Steps: [101/196], Train Loss: [0.078]\n",
      "Epoch: [ 42/ 80], Steps: [196/196], Train Loss: [0.033]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 42/ 80], Average Train Loss: [0.066], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 43/ 80], Steps: [  1/196], Train Loss: [0.044]\n",
      "Epoch: [ 43/ 80], Steps: [101/196], Train Loss: [0.044]\n",
      "Epoch: [ 43/ 80], Steps: [196/196], Train Loss: [0.135]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 43/ 80], Average Train Loss: [0.064], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 44/ 80], Steps: [  1/196], Train Loss: [0.076]\n",
      "Epoch: [ 44/ 80], Steps: [101/196], Train Loss: [0.055]\n",
      "Epoch: [ 44/ 80], Steps: [196/196], Train Loss: [0.159]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 44/ 80], Average Train Loss: [0.062], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 45/ 80], Steps: [  1/196], Train Loss: [0.073]\n",
      "Epoch: [ 45/ 80], Steps: [101/196], Train Loss: [0.059]\n",
      "Epoch: [ 45/ 80], Steps: [196/196], Train Loss: [0.085]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 45/ 80], Average Train Loss: [0.059], Accuracy: [0.840]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 46/ 80], Steps: [  1/196], Train Loss: [0.070]\n",
      "Epoch: [ 46/ 80], Steps: [101/196], Train Loss: [0.040]\n",
      "Epoch: [ 46/ 80], Steps: [196/196], Train Loss: [0.078]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 46/ 80], Average Train Loss: [0.055], Accuracy: [0.837]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 47/ 80], Steps: [  1/196], Train Loss: [0.065]\n",
      "Epoch: [ 47/ 80], Steps: [101/196], Train Loss: [0.054]\n",
      "Epoch: [ 47/ 80], Steps: [196/196], Train Loss: [0.124]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 47/ 80], Average Train Loss: [0.053], Accuracy: [0.839]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 48/ 80], Steps: [  1/196], Train Loss: [0.035]\n",
      "Epoch: [ 48/ 80], Steps: [101/196], Train Loss: [0.042]\n",
      "Epoch: [ 48/ 80], Steps: [196/196], Train Loss: [0.229]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 48/ 80], Average Train Loss: [0.052], Accuracy: [0.836]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 49/ 80], Steps: [  1/196], Train Loss: [0.031]\n",
      "Epoch: [ 49/ 80], Steps: [101/196], Train Loss: [0.049]\n",
      "Epoch: [ 49/ 80], Steps: [196/196], Train Loss: [0.261]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 49/ 80], Average Train Loss: [0.052], Accuracy: [0.838]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 50/ 80], Steps: [  1/196], Train Loss: [0.027]\n",
      "Epoch: [ 50/ 80], Steps: [101/196], Train Loss: [0.041]\n",
      "Epoch: [ 50/ 80], Steps: [196/196], Train Loss: [0.114]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 50/ 80], Average Train Loss: [0.048], Accuracy: [0.841]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 51/ 80], Steps: [  1/196], Train Loss: [0.049]\n",
      "Epoch: [ 51/ 80], Steps: [101/196], Train Loss: [0.028]\n",
      "Epoch: [ 51/ 80], Steps: [196/196], Train Loss: [0.150]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 51/ 80], Average Train Loss: [0.045], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 52/ 80], Steps: [  1/196], Train Loss: [0.053]\n",
      "Epoch: [ 52/ 80], Steps: [101/196], Train Loss: [0.043]\n",
      "Epoch: [ 52/ 80], Steps: [196/196], Train Loss: [0.069]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 52/ 80], Average Train Loss: [0.046], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 53/ 80], Steps: [  1/196], Train Loss: [0.051]\n",
      "Epoch: [ 53/ 80], Steps: [101/196], Train Loss: [0.028]\n",
      "Epoch: [ 53/ 80], Steps: [196/196], Train Loss: [0.070]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 53/ 80], Average Train Loss: [0.042], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 54/ 80], Steps: [  1/196], Train Loss: [0.046]\n",
      "Epoch: [ 54/ 80], Steps: [101/196], Train Loss: [0.046]\n",
      "Epoch: [ 54/ 80], Steps: [196/196], Train Loss: [0.065]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 54/ 80], Average Train Loss: [0.040], Accuracy: [0.840]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 55/ 80], Steps: [  1/196], Train Loss: [0.031]\n",
      "Epoch: [ 55/ 80], Steps: [101/196], Train Loss: [0.027]\n",
      "Epoch: [ 55/ 80], Steps: [196/196], Train Loss: [0.034]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 55/ 80], Average Train Loss: [0.041], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 56/ 80], Steps: [  1/196], Train Loss: [0.062]\n",
      "Epoch: [ 56/ 80], Steps: [101/196], Train Loss: [0.065]\n",
      "Epoch: [ 56/ 80], Steps: [196/196], Train Loss: [0.035]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 56/ 80], Average Train Loss: [0.039], Accuracy: [0.838]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 57/ 80], Steps: [  1/196], Train Loss: [0.028]\n",
      "Epoch: [ 57/ 80], Steps: [101/196], Train Loss: [0.019]\n",
      "Epoch: [ 57/ 80], Steps: [196/196], Train Loss: [0.011]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 57/ 80], Average Train Loss: [0.040], Accuracy: [0.840]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 58/ 80], Steps: [  1/196], Train Loss: [0.036]\n",
      "Epoch: [ 58/ 80], Steps: [101/196], Train Loss: [0.041]\n",
      "Epoch: [ 58/ 80], Steps: [196/196], Train Loss: [0.094]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 58/ 80], Average Train Loss: [0.036], Accuracy: [0.844]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 59/ 80], Steps: [  1/196], Train Loss: [0.055]\n",
      "Epoch: [ 59/ 80], Steps: [101/196], Train Loss: [0.020]\n",
      "Epoch: [ 59/ 80], Steps: [196/196], Train Loss: [0.102]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 59/ 80], Average Train Loss: [0.037], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 60/ 80], Steps: [  1/196], Train Loss: [0.032]\n",
      "Epoch: [ 60/ 80], Steps: [101/196], Train Loss: [0.032]\n",
      "Epoch: [ 60/ 80], Steps: [196/196], Train Loss: [0.097]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 60/ 80], Average Train Loss: [0.032], Accuracy: [0.844]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 61/ 80], Steps: [  1/196], Train Loss: [0.021]\n",
      "Epoch: [ 61/ 80], Steps: [101/196], Train Loss: [0.012]\n",
      "Epoch: [ 61/ 80], Steps: [196/196], Train Loss: [0.117]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 61/ 80], Average Train Loss: [0.034], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 62/ 80], Steps: [  1/196], Train Loss: [0.039]\n",
      "Epoch: [ 62/ 80], Steps: [101/196], Train Loss: [0.032]\n",
      "Epoch: [ 62/ 80], Steps: [196/196], Train Loss: [0.141]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 62/ 80], Average Train Loss: [0.034], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 63/ 80], Steps: [  1/196], Train Loss: [0.032]\n",
      "Epoch: [ 63/ 80], Steps: [101/196], Train Loss: [0.025]\n",
      "Epoch: [ 63/ 80], Steps: [196/196], Train Loss: [0.087]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 63/ 80], Average Train Loss: [0.034], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 64/ 80], Steps: [  1/196], Train Loss: [0.039]\n",
      "Epoch: [ 64/ 80], Steps: [101/196], Train Loss: [0.018]\n",
      "Epoch: [ 64/ 80], Steps: [196/196], Train Loss: [0.019]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 64/ 80], Average Train Loss: [0.030], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 65/ 80], Steps: [  1/196], Train Loss: [0.022]\n",
      "Epoch: [ 65/ 80], Steps: [101/196], Train Loss: [0.024]\n",
      "Epoch: [ 65/ 80], Steps: [196/196], Train Loss: [0.076]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 65/ 80], Average Train Loss: [0.031], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 66/ 80], Steps: [  1/196], Train Loss: [0.014]\n",
      "Epoch: [ 66/ 80], Steps: [101/196], Train Loss: [0.025]\n",
      "Epoch: [ 66/ 80], Steps: [196/196], Train Loss: [0.029]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 66/ 80], Average Train Loss: [0.030], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 67/ 80], Steps: [  1/196], Train Loss: [0.037]\n",
      "Epoch: [ 67/ 80], Steps: [101/196], Train Loss: [0.033]\n",
      "Epoch: [ 67/ 80], Steps: [196/196], Train Loss: [0.060]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 67/ 80], Average Train Loss: [0.030], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 68/ 80], Steps: [  1/196], Train Loss: [0.034]\n",
      "Epoch: [ 68/ 80], Steps: [101/196], Train Loss: [0.021]\n",
      "Epoch: [ 68/ 80], Steps: [196/196], Train Loss: [0.085]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 68/ 80], Average Train Loss: [0.029], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 69/ 80], Steps: [  1/196], Train Loss: [0.038]\n",
      "Epoch: [ 69/ 80], Steps: [101/196], Train Loss: [0.019]\n",
      "Epoch: [ 69/ 80], Steps: [196/196], Train Loss: [0.073]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 69/ 80], Average Train Loss: [0.031], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 70/ 80], Steps: [  1/196], Train Loss: [0.020]\n",
      "Epoch: [ 70/ 80], Steps: [101/196], Train Loss: [0.026]\n",
      "Epoch: [ 70/ 80], Steps: [196/196], Train Loss: [0.079]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 70/ 80], Average Train Loss: [0.029], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 71/ 80], Steps: [  1/196], Train Loss: [0.027]\n",
      "Epoch: [ 71/ 80], Steps: [101/196], Train Loss: [0.031]\n",
      "Epoch: [ 71/ 80], Steps: [196/196], Train Loss: [0.042]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 71/ 80], Average Train Loss: [0.028], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 72/ 80], Steps: [  1/196], Train Loss: [0.043]\n",
      "Epoch: [ 72/ 80], Steps: [101/196], Train Loss: [0.036]\n",
      "Epoch: [ 72/ 80], Steps: [196/196], Train Loss: [0.028]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 72/ 80], Average Train Loss: [0.027], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 73/ 80], Steps: [  1/196], Train Loss: [0.046]\n",
      "Epoch: [ 73/ 80], Steps: [101/196], Train Loss: [0.020]\n",
      "Epoch: [ 73/ 80], Steps: [196/196], Train Loss: [0.244]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 73/ 80], Average Train Loss: [0.028], Accuracy: [0.841]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 74/ 80], Steps: [  1/196], Train Loss: [0.027]\n",
      "Epoch: [ 74/ 80], Steps: [101/196], Train Loss: [0.030]\n",
      "Epoch: [ 74/ 80], Steps: [196/196], Train Loss: [0.044]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 74/ 80], Average Train Loss: [0.028], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 75/ 80], Steps: [  1/196], Train Loss: [0.024]\n",
      "Epoch: [ 75/ 80], Steps: [101/196], Train Loss: [0.049]\n",
      "Epoch: [ 75/ 80], Steps: [196/196], Train Loss: [0.182]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 75/ 80], Average Train Loss: [0.030], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 76/ 80], Steps: [  1/196], Train Loss: [0.042]\n",
      "Epoch: [ 76/ 80], Steps: [101/196], Train Loss: [0.019]\n",
      "Epoch: [ 76/ 80], Steps: [196/196], Train Loss: [0.079]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 76/ 80], Average Train Loss: [0.029], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 77/ 80], Steps: [  1/196], Train Loss: [0.023]\n",
      "Epoch: [ 77/ 80], Steps: [101/196], Train Loss: [0.031]\n",
      "Epoch: [ 77/ 80], Steps: [196/196], Train Loss: [0.055]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 77/ 80], Average Train Loss: [0.027], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 78/ 80], Steps: [  1/196], Train Loss: [0.028]\n",
      "Epoch: [ 78/ 80], Steps: [101/196], Train Loss: [0.021]\n",
      "Epoch: [ 78/ 80], Steps: [196/196], Train Loss: [0.195]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 78/ 80], Average Train Loss: [0.028], Accuracy: [0.842]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 79/ 80], Steps: [  1/196], Train Loss: [0.052]\n",
      "Epoch: [ 79/ 80], Steps: [101/196], Train Loss: [0.020]\n",
      "Epoch: [ 79/ 80], Steps: [196/196], Train Loss: [0.030]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 79/ 80], Average Train Loss: [0.027], Accuracy: [0.843]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 80/ 80], Steps: [  1/196], Train Loss: [0.026]\n",
      "Epoch: [ 80/ 80], Steps: [101/196], Train Loss: [0.035]\n",
      "Epoch: [ 80/ 80], Steps: [196/196], Train Loss: [0.057]\n",
      "--------------------------------------------------\n",
      "Epoch: [ 80/ 80], Average Train Loss: [0.027], Accuracy: [0.841]\n",
      "--------------------------------------------------\n",
      "================================================================================\n",
      "End of validation the best Accuracy is:  0.844, save the best ckpt file in ./BestCheckpoint/resnet50-best.ckpt\n"
     ]
    }
   ],
   "source": [
    "# 开始循环训练\n",
    "print(\"Start Training Loop ...\")\n",
    "\n",
    "for epoch in range(num_epochs):\n",
    "    curr_loss = train(data_loader_train, epoch)\n",
    "    curr_acc = evaluate(data_loader_val)\n",
    "\n",
    "    print(\"-\" * 50)\n",
    "    print(\"Epoch: [%3d/%3d], Average Train Loss: [%5.3f], Accuracy: [%5.3f]\" % (\n",
    "        epoch+1, num_epochs, curr_loss, curr_acc\n",
    "    ))\n",
    "    print(\"-\" * 50)\n",
    "\n",
    "    # 保存当前预测准确率最高的模型\n",
    "    if curr_acc > best_acc:\n",
    "        best_acc = curr_acc\n",
    "        ms.save_checkpoint(network, best_ckpt_path)\n",
    "\n",
    "print(\"=\" * 80)\n",
    "print(f\"End of validation the best Accuracy is: {best_acc: 5.3f}, \"\n",
    "      f\"save the best ckpt file in {best_ckpt_path}\", flush=True)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "6ba2fa94",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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sSbhz/+clz/4wfTvDTc8+GuCgOhlL0v3kORPj4jSr6dO8cIXEh09mqpCT9HpjOZ69bKXpTfgXe/S/3b6J5FSKf06zEL+JObUJ5vTX+9cqpCW7NyZvv7067njDqJvfYvHFYvpX9mG9euJrrgindRP/7e77iL60pfSvnmkeOELiY4fJ/rMZ5bqoii9n+Vyus94Op//fPoJ9BS33kr0ve899H23eOUrib7znfThltTraRseLTB2MXaJHp9jd7U4156ZM+GFL0zH1He+s1TXbqfXsG3bkl7j+c9Px+Hf//1SXK+XmkSdjZzxNwn796fCixe8IO2UT32K6DWvSX+n/FC8+93pTz2uvTYValx8cboCvP329KdT8/Np3BvfSPRnf5Z+8rnttnTy+eQnlyanh+L664l+/ufTn+ns2ZO2MUnSn8Rcf336UxwioquuSs/5vvele1rbty/tKcmfxOzalU6gv/mb6Q0eG0sHv9zfJUp/E/y+96WD4cYb0323D30o/X3w4uJSXKGQXv9nPpN+RTkxke5ZXXop0Xvekz6AT3lKeoxTPyOrVvnv0VfKm96U/tTs9a9P+3nbtvRB/da30p8BVSo8/rzzUmHOr/xK+hvm978//anPg331+mD8l/+SPiQvelF67quuSh+oO+9Mz3/ggN6TfqTA2MXYfbyO3dXiXHtmzoTf/m2i//t/07H/trelz8THP5723U03LX3b9eY3p9f66lenP4Fcvz79ie8p46lH+xuPh83D/TnEqZ+F3HOPcy9/uXOVinPj48699a3pzzhOQeTcW95iH+PEifTfNm92LpNxbt06557zHOc+/GEed/Bg+tObYtG5qSnn3v729Gcny/0kxrn0p1TveU/6s5Js1rnpaeduuMG5225bitm927lnPjP9aRQR/3mM9ZOYe+5x7rnPTX9eNTXl3BvfmP4EiMi5j36Ux37qU87t2JGe+4ornLv5Zrud3/62c1ddlcbJn5R9+cvOPe1pafvGxpx78YvTNpzOg/1M53WvS3/yI7nuOucuuYTXnTjh3C/+YnpN2axzl12mr+fUz8je8570JzybNzuXyzn3jGcs/QxKtul05M/InEt/HvQ7v5P+zCmbTc//1Kc698d/nP6U7ZEGYxdj9/E6dleLc/mZeaifQP70T9vXev/9aT/Vas7l88496UnO/eM/6rh9+9JjFAppW//z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",
      "text/plain": [
       "<Figure size 640x480 with 6 Axes>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "\n",
    "def visualize_model(best_ckpt_path, dataset_val):\n",
    "    num_class = 10\n",
    "    net = resnet50(num_class)\n",
    "    # 加载模型参数\n",
    "    param_dict = ms.load_checkpoint(best_ckpt_path)\n",
    "    ms.load_param_into_net(net, param_dict)\n",
    "    # 加载验证集的数据进行验证\n",
    "    data = next(dataset_val.create_dict_iterator())\n",
    "    images = data[\"image\"]\n",
    "    labels = data[\"label\"]\n",
    "    # 预测图像类别\n",
    "    output = net(data['image'])\n",
    "    pred = np.argmax(output.asnumpy(), axis=1)\n",
    "\n",
    "    # 图像分类\n",
    "    classes = []\n",
    "\n",
    "    with open(data_dir + \"/batches.meta.txt\", \"r\") as f:\n",
    "        for line in f:\n",
    "            line = line.rstrip()\n",
    "            if line:\n",
    "                classes.append(line)\n",
    "\n",
    "    # 显示图像及图像的预测值\n",
    "    plt.figure()\n",
    "    for i in range(6):\n",
    "        plt.subplot(2, 3, i + 1)\n",
    "        # 若预测正确，显示为蓝色；若预测错误，显示为红色\n",
    "        color = 'blue' if pred[i] == labels.asnumpy()[i] else 'red'\n",
    "        plt.title('predict:{}'.format(classes[pred[i]]), color=color)\n",
    "        picture_show = np.transpose(images.asnumpy()[i], (1, 2, 0))\n",
    "        mean = np.array([0.4914, 0.4822, 0.4465])\n",
    "        std = np.array([0.2023, 0.1994, 0.2010])\n",
    "        picture_show = std * picture_show + mean\n",
    "        picture_show = np.clip(picture_show, 0, 1)\n",
    "        plt.imshow(picture_show)\n",
    "        plt.axis('off')\n",
    "\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "# 使用测试数据集进行验证\n",
    "visualize_model(best_ckpt_path=best_ckpt_path, dataset_val=dataset_val)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "51781c1e-42da-48b6-8707-b93855c37834",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.16"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
